﻿#include "SEAJunctionUserDefWidget.h"
#include "ui_SEAJunctionUserDefWidget.h"
#include "SEAJunctionUserDefSelectDialog.h"

#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEAAbstractJunction.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsSpectraManager.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbstractSpectra.h"

#include <QComboBox>

#define JunUserDef_SubsysID Qt::UserRole
#define JunUserDef_SubsysIndex Qt::UserRole+1
#define JunUserDef_ComboboxRow "ComboboxRow"
#define JunUserDef_ComboboxColumn "ComboboxColumn"
#define JunUserDef_Analytical -2
#define JunUserDef_Reciprocal -1

namespace GUI
{
    SEAJunctionUserDefWidget::SEAJunctionUserDefWidget(QWidget * parent):
        GUIWidgetBase(parent)
    {
        _ui = new Ui::SEAJunctionUserDefWidget();
        _ui->setupUi(this);

        _ui->lineEdit_MatrixForm->setText("Symmetric");
        _ui->lineEdit_MatrixForm->setEnabled(false);

        //隐藏行表头
        _ui->tableWidget->horizontalHeader()->setVisible(false);
        //隐藏列表头
        _ui->tableWidget->verticalHeader()->setVisible(false);
    }

    SEAJunctionUserDefWidget::~SEAJunctionUserDefWidget()
    {
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
    }

    void SEAJunctionUserDefWidget::initTable(QList<int> subSysIds)
    {
        initTableTitle(subSysIds);
        initTableValue(subSysIds);
    }

    void SEAJunctionUserDefWidget::setDataToWidget(Acoustics::FITKSEAAbstractJunction * junData)
    {
        if (_SEAModel == nullptr && _SEAModel->getSEASubSysManager() == nullptr)return;
        if (junData == nullptr)return;
        QString matrixFrom = junData->getMatrixForm();
        _ui->lineEdit_MatrixForm->setText(matrixFrom);

        QList<Acoustics::FITKSEAJunUserDefStr> defStrs = junData->getUserDefs();
        for (Acoustics::FITKSEAJunUserDefStr str : defStrs) {
            QComboBox* comboBox = findComboBox(str);
            if (comboBox == nullptr)continue;
            QSignalBlocker blocker1(comboBox);
            if (str._spectrumID == JunUserDef_Reciprocal && comboBox->findData(str._spectrumID) == -1) {
                comboBox->insertItem(0, "Reciprocal", JunUserDef_Reciprocal);
            }
            else if (str._spectrumID != JunUserDef_Reciprocal && comboBox->findData(JunUserDef_Reciprocal) != -1) {
                comboBox->removeItem(0);
            }
            comboBox->setCurrentIndex(comboBox->findData(str._spectrumID));
        }
    }

    void SEAJunctionUserDefWidget::getDataFromWidget(Acoustics::FITKSEAAbstractJunction * junData)
    {
        if (junData == nullptr)return;
        QString matrixFrom = _ui->lineEdit_MatrixForm->text();
        junData->setMatrixForm(matrixFrom);

        QList<Acoustics::FITKSEAJunUserDefStr> defStrs = {};
        QList<QComboBox*> comboBoxs = _ui->tableWidget->findChildren<QComboBox*>();
        for (QComboBox* comboBox : comboBoxs) {
            if (comboBox == nullptr)continue;
            Acoustics::FITKSEAJunUserDefStr defStr;
            int rowIndex = comboBox->property(JunUserDef_ComboboxRow).toInt();
            int columnIndex = comboBox->property(JunUserDef_ComboboxColumn).toInt();
            int spectraID = comboBox->currentData().toInt();
            QTableWidgetItem* rowItem = _ui->tableWidget->item(rowIndex, 0);
            if (rowItem) {
                defStr._subsysRowID = rowItem->data(JunUserDef_SubsysID).toInt();
                defStr._subsysRowIndex = rowItem->data(JunUserDef_SubsysIndex).toInt();
            }
            QTableWidgetItem* columnItem = _ui->tableWidget->item(0, columnIndex);
            if (columnItem) {
                defStr._subsysColumnID = columnItem->data(JunUserDef_SubsysID).toInt();
                defStr._subsysColumnIndex = columnItem->data(JunUserDef_SubsysIndex).toInt();
            }
            defStr._spectrumID = spectraID;
            defStrs.append(defStr);
        }
        junData->replaceUserDefs(defStrs);
    }

    void SEAJunctionUserDefWidget::on_pushButton_SetAll_clicked()
    {
        SEAJunctionUserDefSelectDialog dialog;
        if (dialog.exec() != QDialog::Accepted)return;

        int specID = dialog.getCurrentData();
        QList<QComboBox*> comboBoxs = _ui->tableWidget->findChildren<QComboBox*>();
        for (QComboBox* comboBox : comboBoxs) {
            QSignalBlocker blocker1(comboBox);
            if (comboBox == nullptr)continue;
            int rowIndex = comboBox->property(JunUserDef_ComboboxRow).toInt();
            int columnIndex = comboBox->property(JunUserDef_ComboboxColumn).toInt();
            if (rowIndex < columnIndex) {
                int index = comboBox->findData(JunUserDef_Reciprocal);
                if (index != -1) {
                    comboBox->removeItem(index);
                }
                comboBox->setCurrentIndex(comboBox->findData(specID));
            }
            else if (columnIndex < rowIndex) {
                int index = comboBox->findData(JunUserDef_Reciprocal);
                if (index == -1) {
                    comboBox->insertItem(0, "Reciprocal", JunUserDef_Reciprocal);
                    comboBox->setCurrentIndex(comboBox->findData(JunUserDef_Reciprocal));
                }
                else {
                    comboBox->setCurrentIndex(index);
                }
            }
        }
    }

    void SEAJunctionUserDefWidget::slotComboBoxSelect()
    {
        QComboBox* comboBox = dynamic_cast<QComboBox*>(sender());
        if (comboBox == nullptr)return;
        int rowIndex = comboBox->property(JunUserDef_ComboboxRow).toInt();
        int columnIndex = comboBox->property(JunUserDef_ComboboxColumn).toInt();
        int specID = comboBox->currentData().toInt();
        QComboBox* symmetryComboBox = dynamic_cast<QComboBox*>(_ui->tableWidget->cellWidget(columnIndex, rowIndex));
        if (symmetryComboBox == nullptr)return;

        QSignalBlocker blocker1(comboBox);
        QSignalBlocker blocker2(symmetryComboBox);

        if (specID == JunUserDef_Reciprocal) {

        }
        else {
            //当前控件处理
            int index = comboBox->findData(JunUserDef_Reciprocal);
            if (index == -1) {

            }
            else {
                comboBox->removeItem(index);
            }

            //判断对称控件是否有Reciprocal
            index = symmetryComboBox->findData(JunUserDef_Reciprocal);
            if (index == -1) {
                symmetryComboBox->insertItem(0, "Reciprocal", JunUserDef_Reciprocal);
                symmetryComboBox->setCurrentIndex(symmetryComboBox->findData(JunUserDef_Reciprocal));
            }
            else {
                symmetryComboBox->setCurrentIndex(index);
            }
        }
    }

    void SEAJunctionUserDefWidget::initTableTitle(QList<int> subSysIds)
    {
        if (_SEAModel == nullptr && _SEAModel->getSEASubSysManager() == nullptr)return;
        //重置
        _ui->tableWidget->clear();
        _ui->tableWidget->setRowCount(1);
        _ui->tableWidget->setColumnCount(1);
        QTableWidgetItem* item = new QTableWidgetItem();
        item->setText(tr("From\\To"));
        item->setFlags(Qt::ItemFlag::ItemIsEnabled);
        _ui->tableWidget->setItem(0, 0, item);
        //设置列标题
        int count = 1;
        for (int id : subSysIds) {
            Acoustics::FITKAbstractSEASubSys* subSysData = _SEAModel->getSEASubSysManager()->getDataByID(id);
            if (subSysData == nullptr)continue;
            QString name = subSysData->getDataObjectName();
            int id = subSysData->getDataObjectID();
            Acoustics::FITKAbstractSEASubSys::SEASubSysType type = subSysData->getSEASubSysType();
            switch (type)
            {
            case Acoustics::FITKAbstractSEASubSys::SEABeam: {
                _ui->tableWidget->setRowCount(++count);
                _ui->tableWidget->setColumnCount(count);
                item = new QTableWidgetItem();
                item->setText(name + "-X");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 0);
                _ui->tableWidget->setItem(0, count - 1, item);
                item = new QTableWidgetItem();
                item->setText(name + "-X");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 0);
                _ui->tableWidget->setItem(count - 1, 0, item);

                _ui->tableWidget->setRowCount(++count);
                _ui->tableWidget->setColumnCount(count);
                item = new QTableWidgetItem();
                item->setText(name + "-Y");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 1);
                _ui->tableWidget->setItem(0, count - 1, item);
                item = new QTableWidgetItem();
                item->setText(name + "-Y");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 1);
                _ui->tableWidget->setItem(count - 1, 0, item);

                _ui->tableWidget->setRowCount(++count);
                _ui->tableWidget->setColumnCount(count);
                item = new QTableWidgetItem();
                item->setText(name + "-E");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 2);
                _ui->tableWidget->setItem(0, count - 1, item);
                item = new QTableWidgetItem();
                item->setText(name + "-E");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 2);
                _ui->tableWidget->setItem(count - 1, 0, item);

                _ui->tableWidget->setRowCount(++count);
                _ui->tableWidget->setColumnCount(count);
                item = new QTableWidgetItem();
                item->setText(name + "-T");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 3);
                _ui->tableWidget->setItem(0, count - 1, item);
                item = new QTableWidgetItem();
                item->setText(name + "-T");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 3);
                _ui->tableWidget->setItem(count - 1, 0, item);
                break;
            }
            case Acoustics::FITKAbstractSEASubSys::SEAFlatPlate:
            case Acoustics::FITKAbstractSEASubSys::SEASinglyCurvedShell:
            case Acoustics::FITKAbstractSEASubSys::SEADoublyCurvedShell:
            case Acoustics::FITKAbstractSEASubSys::SEACylinderShell: {
                _ui->tableWidget->setRowCount(++count);
                _ui->tableWidget->setColumnCount(count);
                item = new QTableWidgetItem();
                item->setText(name + "-E");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 0);
                _ui->tableWidget->setItem(0, count - 1, item);
                item = new QTableWidgetItem();
                item->setText(name + "-E");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 0);
                _ui->tableWidget->setItem(count - 1, 0, item);

                _ui->tableWidget->setRowCount(++count);
                _ui->tableWidget->setColumnCount(count);
                item = new QTableWidgetItem();
                item->setText(name + "-S");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 1);
                _ui->tableWidget->setItem(0, count - 1, item);
                item = new QTableWidgetItem();
                item->setText(name + "-S");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 1);
                _ui->tableWidget->setItem(count - 1, 0, item);

                _ui->tableWidget->setRowCount(++count);
                _ui->tableWidget->setColumnCount(count);
                item = new QTableWidgetItem();
                item->setText(name + "-F");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 2);
                _ui->tableWidget->setItem(0, count - 1, item);
                item = new QTableWidgetItem();
                item->setText(name + "-F");
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 2);
                _ui->tableWidget->setItem(count - 1, 0, item);
                break;
            }
            case Acoustics::FITKAbstractSEASubSys::SEACavity: {
                _ui->tableWidget->setRowCount(++count);
                _ui->tableWidget->setColumnCount(count);
                item = new QTableWidgetItem();
                item->setText(name);
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 0);
                _ui->tableWidget->setItem(0, count - 1, item);
                item = new QTableWidgetItem();
                item->setText(name);
                item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                item->setData(JunUserDef_SubsysID, id);
                item->setData(JunUserDef_SubsysIndex, 0);
                _ui->tableWidget->setItem(count - 1, 0, item);
                break;
            }
            }
        }

        //自适应
        if (_ui->tableWidget->columnCount() > 0) {
            _ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        }
    }


    void SEAJunctionUserDefWidget::initTableValue(QList<int> subSysIds)
    {
        //行列数计算
        int count = 0;
        for (int id : subSysIds) {
            Acoustics::FITKAbstractSEASubSys* subSysData = _SEAModel->getSEASubSysManager()->getDataByID(id);
            if (subSysData == nullptr)continue;
            Acoustics::FITKAbstractSEASubSys::SEASubSysType type = subSysData->getSEASubSysType();
            switch (type)
            {
            case Acoustics::FITKAbstractSEASubSys::SEABeam: count += 4; break;
            case Acoustics::FITKAbstractSEASubSys::SEAFlatPlate:
            case Acoustics::FITKAbstractSEASubSys::SEASinglyCurvedShell:
            case Acoustics::FITKAbstractSEASubSys::SEADoublyCurvedShell:
            case Acoustics::FITKAbstractSEASubSys::SEACylinderShell: count += 3; break;
            case Acoustics::FITKAbstractSEASubSys::SEACavity: count += 1; break;
            }
        }

        //行
        for (int i = 1; i <= count; i++) {
            //列
            for (int j = 1; j <= count; j++) {
                if (i < j) {
                    QComboBox* box = createComboBox(i, j);
                    QSignalBlocker blocker1(box);
                    box->setCurrentIndex(box->findData(JunUserDef_Analytical));
                    box->setProperty(JunUserDef_ComboboxRow, i);
                    box->setProperty(JunUserDef_ComboboxColumn, j);
                    _ui->tableWidget->setCellWidget(i, j, box);
                }
                else if (i == j) {
                    QTableWidgetItem* item = new QTableWidgetItem();
                    item->setFlags(Qt::ItemFlag::ItemIsEnabled);
                    _ui->tableWidget->setItem(i, j, item);
                }
                else {
                    QComboBox* box = createComboBox(i, j);
                    QSignalBlocker blocker1(box);
                    box->setCurrentIndex(box->findData(JunUserDef_Reciprocal));
                    box->setProperty(JunUserDef_ComboboxRow, i);
                    box->setProperty(JunUserDef_ComboboxColumn, j);
                    _ui->tableWidget->setCellWidget(i, j, box);
                }
            }
        }
    }

    QComboBox * SEAJunctionUserDefWidget::createComboBox(int rowIndex, int colmunIndex)
    {
        QComboBox* box = new QComboBox(this);
        if (colmunIndex < rowIndex) {
            box->addItem("Reciprocal", JunUserDef_Reciprocal);
        }
        box->addItem("Analytical", JunUserDef_Analytical);
        if (_physics == nullptr && _physics->getFITKAcousticsSpectraManager() == nullptr)return box;
        for (Acoustics::FITKAcousticsAbstractSpectra* specData :
            _physics->getFITKAcousticsSpectraManager()->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::AcousticsSpectraType::Coupling))
        {
            if(specData == nullptr)continue;
            box->addItem(specData->getDataObjectName(), specData->getDataObjectID());
        }

        connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(slotComboBoxSelect()));
        return box;
    }

    QComboBox * SEAJunctionUserDefWidget::findComboBox(Acoustics::FITKSEAJunUserDefStr str)
    {
        int rowInde = -1, colmunIndex = -1;
        for (int i = 1; i < _ui->tableWidget->rowCount(); i++) {
            QTableWidgetItem* item = _ui->tableWidget->item(i, 0);
            if (item == nullptr)continue;
            if (str._subsysRowID == item->data(JunUserDef_SubsysID).toInt() && str._subsysRowIndex == item->data(JunUserDef_SubsysIndex).toInt()) {
                rowInde = i;
                break;
            }
            
        }
        for (int i = 1; i < _ui->tableWidget->columnCount(); i++) {
            QTableWidgetItem* item = _ui->tableWidget->item(0, i);
            if (item == nullptr)continue;
            if (str._subsysColumnID == item->data(JunUserDef_SubsysID).toInt() && str._subsysColumnIndex == item->data(JunUserDef_SubsysIndex).toInt()) {
                colmunIndex = i;
                break;
            }
        }

        return dynamic_cast<QComboBox*>(_ui->tableWidget->cellWidget(rowInde, colmunIndex));
    }
}
